Go训练营第五课问题收集
2021年11月4日 更新
开启更多功能,提升办公效能
  1. 业务服务升级,http服务优雅退出,会等所有的http请求处理完成或者context超时后关闭服务。如果http服务某个api异步再起goroutine执行其他任务(假设任务需要1分钟),当前请求早已经返回。当触发Signal。服务等候关闭(所有htpp请求完成后),但实际还有(野生goroutine)任务还没执行完,这样的情况是不是容易产生脏数据。所有优雅退出是不是都有可能伴随野生goroutine未执行完服务就被关闭的风险了,所有的平滑升级都有可能产生脏数据了?这种情况怎么避免?b站有出现类似情况么?有没有用户反映某些数据不一致问题。<所以创建goroutine时候要想清楚他的生命周期,并且提供管控机制即可以结束它,即每个goroutine都要接收关闭信号的处理,方便的做法是将goroutine做个管理类似job/worker的生产者消费者模式>
  1. 在并发编程中,大量的goroutine 会产生大量的 资源竞争,为了解决资源竞争 又会大量的加锁,大量加锁又会导致并发降低,如何 权衡这3者关系
  1. 在 rpc 服务中,业务快速增长阶段,使用协程池是否有必要?业务稳定后使用协程池是否有必要?
  1. 在开启大量goroutine时 会导致CPU过高,这时候需要控制goroutine数量,如何控制比较合适,或者根据什么条件来控制,
  1. channel实现也使用了mutex ,为撒通常channel比mutex并发效果好
  1. 并发的代码如何调试呢?
  1. 一般创建一个协程池数量怎么给的啊?
  1. 系统能同时起多少个协程和什么相关?一个goroutine的内存是多大?
  1. 多线程运行多个核,才叫并行吧?在单核心上而且在周期之内才叫并行?难道之前的理解错了?
  1. go 的 gorouting 跟C#.net 中的Task 是不是一模一样的?
  1. 并行并发,无论是单词(concurrency: 并发,parallel: 并行),还是解释(并发是场景,如高并发;并行是处理方法,如并行运算),能再简单明确下各自是哪个吗...
  1. listen的时候,如果是多核的情况下,会开启几个goroutine进行listen
  1. 什么时候使用os.exit什么时候使用panic呢
  1. http.listen会给每个请求开一个goroutine吗?如果是,在高并发的时候怎么控制goroutine得数量?
  1. http sever优雅退出的时候,会阻塞等待所有goroutine全结束再退出服务吗? 优雅在什么地方?
  1. 什么场景适合使用并发,什么场景不适合并发?
  1. 什么是goroutine泄露?是goroutine达到一定数量级,导致runtime内存泄露吗?

是goroutine异常,不能正常退出,占用系统资源无法释放。

  1. 注意 3 点:1. 把并发行为交给调用者;2.知道goroutine什么时候退出; 3.可以控制goroutine的退出。我想问:2 和 3 不是同一点么,都是管控 goroutine 的生命周期。

究的其实有些差别,比如2是正常情况什么时候退出,3是当出现一些异常时控制goroutine退出,but总归来说,就是要能掌控goroutine的退出。

  1. 什么是用户态,什么是内核态啊?

https://blog.csdn.net/JMW1407/article/details/107901155, 简单讲就是用户态是应用程序控制的范围,内核态是操作系统控制的范围,

  1. 在设计Goroutine Pool 的时候,是用控制最大启动数量(处理完任务就退出goroutine,类似Master-Work并发模型),还是启动固定的goroutine 一直在竞争读取chan中的数据呢(chan为空时,会有大量的goroutine处于挂起状态)?

两种方式其实都可以,不过控制最大启动数量更好,参考fasthttp的设计。https://github.com/valyala/fasthttp

  1. 老师刚刚讲的这段代码,是否需要在外部添加个for呢?不然的话,当channel还有剩余缓冲区的时候,select不是会直接结束嘛(个人理解错了,以为传入的context是用于做超时控制的,因此误以为select直接结束的话,context就没意义了)?不会,select要成功的执行一次case条件才会退出,否则继续等待。这也是为什么select{}表示永久阻塞,因为永远不会有一个可以执行的case。补充一条,这里能判断chan满了吗?
func (t *Tracker) Event(ctx context.Context, data string) error {
select {
case t.ch <- data:
return nil
case <-ctx.Done():
return ctx.Err()
}
}


  1. 优雅关闭服务的时候,有buffer channel 还在处理,如何保证顺利退出,channnel里的存量数据都能处理完

柠檬: 这个buffer channel指的是类似于异步任务队列是吗?

目前来看,大部分实现并未考虑这块。一般我们也不用这个优雅关闭,会通过路由摘除,等待流量完全停止后,再重启进程。

(原来我不是回答这题的,点错了)

  1. 调用者和被调用者是一个相对的概念。比如, methodA 内部启了个goroutine. methodB也可能启一个goroutine 调用methodA啊。
  1. Go语言有类似volatile禁止编译器指令排或编译优化的方法吗?另外保持可见性,使之能通过CSP或DataRace处理吗?
  1. nginx memory barrier ?
  • MESI
  • 只需要通过CSP(chan)或DataRace(sync, atomic)等搞定Happens Before即可
  1. Go memory model中如果设置了M=1的情况下,关于A、B的顺序现象会有差异吗
  1. 如果很多很多数据都存map,会出现泄露吗

柠檬:如果是全局或者长生命周期的map,那就是会了。一般这种应该用lru cache

  1. 开发过程中,有没有必要使用协程池,如果有,用在什么场景呢,有没有什么要注意的

柠檬:有场景,只在于对性能要求比较高的场景,比如频繁大量异步任务,或者长连接处理。

  1. 在一个goroutine中,有一个for循环中使用select从多个chan读取或写入数据,会不会造成该goroutine长时间占用着CPU时间轮片,从而导致其他的goroutine长期无法获取CPU时间轮片。

柠檬:时间很短,影响不大,复杂方法编译器有添加检测是否被抢占的代码的。同时1.14后有基于信号的强制抢占机制。

  1. 前几节课老师说不要写这种祼的野的go func(),要包一层Go(f func(){}),昨天的goroutine写的例子,感觉有好多类似野的写法,有点迷失了

柠檬:一般线上业务尽量不要因为不完善逻辑panic导致进程挂掉,所以直接go func不可取,包装一层。

  1. groutine的生命周期管理推荐使用waitgroup还是context?起goroutine建议都放在在main函数?

柠檬:wg和ctx使用场景不同,建议多用用感受下。

起goroutine看当前是否需要。

  1. 老师的示例代码可不可以共享到github上,谢谢……课上要看代码,看来还真得预习呀
  1. 比如像一些后台操作要记录操作记录,这时通过goroutine去处理,但是如果里面报错了要怎么处理啊?(我的理解是传一个chan进去,外面通过<-chan的值进行相关判断,这时就感觉变成的串行化了,就失去了goroutine后台跑的意义了)
  1. 对于耗时任务,context怎么处理,或者怎么控制这样的任务。
  1. media里的map中value怎么是[]interface{}呢,怎么不直接用interface{}
  1. 如果每个调用方法都传context做超时控制,那是不是每个方法都需要 select case <-ctx.done. 感觉有些麻烦。有更好的方式吗?
  1. Go语言怎么保证多线程下共享变量之间的可见性呢?比如Java提供了volatile关键字,可以确保变量及时刷新到主存中。
  1. goroutine的使用要考虑协程池么,课上好像没有相关内容,有没有什么推荐的库
  1. 毛老师视频第三周1视频中1小时处讲的5.go 代码中go tr.Run() 中的for循环与tr.Shutdown(ctx) 中的close(ch),是close(ch) 先行发生于for 循环这么理解对吗?
  1. 如果要同时操作redis集群中分散在不同分片的很多key,有啥好办法?单实例可以用lua脚本操作,集群对lua脚本有限制,然后一个个请求性能太差了。
  1. grpc使用http对外暴露,怎么定义服务的url 地址呢?
  1. 一个查看评论的请求过来,cache miss, job做批量缓存,那当前请求怎么返回数据呢?是先查数据库拿到当前页的数据,在发命令到job做批量缓存吗?